package com.zmn.oms.zmn.business.impl.refund;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.base.common.data.common.dro.tags.TagsDRO;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderRefundConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dio.normal.master.ReworkRefundDIO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.vo.KVDict;
import com.zmn.oms.model.dto.work.refund.RefundDTO;
import com.zmn.oms.model.entity.master.OrderMaster;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.master.OrderMasterService;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.refund.ZsRefundBService;
import com.zmn.oms.zmn.normal.business.interfaces.refund.RefundBService;
import com.zmn.pay.common.constant.PayConsts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ZsRefundBServiceImpl implements ZsRefundBService {

    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private BaseCodeService baseCodeService;
    @Autowired
    private OrderMasterService orderMasterService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private RefundBService refundBService;

    @Override
    public void addRefundOrderByEngineer(ReworkRefundDIO reworkRefundDIO) throws Exception {
        OrderWork rework = orderWorkService.findMasterWorkDetail(reworkRefundDIO.getOrderId(), reworkRefundDIO.getWorkId(), reworkRefundDIO.getMasterId());
        if (Objects.isNull(rework)) {
            throw new OmsBaseException("无效的工单");
        }

        if (!Objects.equals(rework.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            throw new OmsBaseException("工单不在进行中");
        }

        OrderWork original = orderWorkService.findOrderWorkByKey(rework.getOriginalId(), rework.getOriginalId());

        // 同一个工程师，申请过后，不可再次申请
        if (NumberUtil.isNotNullOrZero(original.getRefundTargetWorkId())) {
            OrderWork reworkRefund = orderWorkService.findOrderWorkByKey(original.getOrderId(), original.getRefundTargetWorkId());
            if (Objects.equals(String.valueOf(reworkRefund.getReceiverId()), String.valueOf(reworkRefundDIO.getMasterId()))
                    && Objects.equals(reworkRefund.getReceiverType(), GlobalConsts.OPERATE_USER_TYPE_MASTER)
                    && Objects.equals(reworkRefund.getOrderId(), reworkRefundDIO.getOrderId())) {
                throw new OmsBaseException("你已申请过退款，不可再次操作");
            }
        }

        RefundDTO refundDTO = BeanMapper.map(reworkRefundDIO, RefundDTO.class);
        refundDTO.setOrderId(original.getOrderId());
        refundDTO.setWorkId(original.getWorkId());
        refundDTO.setRefundWorkId(reworkRefundDIO.getOrderId());
        refundDTO.setOperator(reworkRefundDIO.getMasterName());
        refundDTO.setOperatorId((long) reworkRefundDIO.getMasterId());
        refundDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_MASTER);

        refundDTO.setMasterId(original.getMasterId());
        refundDTO.setMasterName(original.getMasterName());
        refundDTO.setCompanyId(original.getManageCompanyId());
        refundDTO.setCompanyName(original.getManageCompanyName());
        refundDTO.setBizMode(original.getBizMode());
        refundDTO.setStatus(original.getStatus());
        refundDTO.setResultStatus(original.getResultStatus());
        // 不需要审核
        refundDTO.setReview(false);

        // 把跟单缘由转换为退款缘由
        List<TagsDRO> baseCodeMapList = baseCodeService.listBaseCodeMap(GlobalConsts.PLAT_MARK_ZMN, OrderRefundConsts.BASE_CODE_MAP_ONE_TYPE_OMS_REFUND_REASON, null, null);
        if (CollectionUtil.isNullOrEmpty(baseCodeMapList)) {
            throw new OmsBaseException("未找到退款缘由配置");
        }
        baseCodeMapList.forEach(e -> {
            if (Objects.equals(e.getTwoTypeId(), reworkRefundDIO.getReasonId())) {
                refundDTO.setReasonList(Lists.newArrayList(KVDict.builder().value(e.getTagId()).text(e.getName()).build()));
            }
        });
        // 没找到对应的缘由映射，就把跟单缘由塞进去
        if (CollectionUtil.isNullOrEmpty(refundDTO.getReasonList())) {
            refundDTO.setReasonList(Lists.newArrayList(KVDict.builder().value(reworkRefundDIO.getReasonId()).text(reworkRefundDIO.getReasonName()).build()));
        }
        log.info("[{}]创建退款单：【{}】", refundDTO.getOrderId(), JSON.toJSONString(refundDTO));

        // 多工程师
        if (Objects.equals(original.getMultiMaster(), GlobalConsts.YES)) {
            List<OrderMaster> orderMasterList = orderMasterService.listMasterByWorkId(reworkRefundDIO.getOrderId(), reworkRefundDIO.getWorkId());
            refundDTO.setMasterList(orderMasterList.stream().map(OrderMaster::getMasterId).collect(Collectors.toList()));
        }
        refundDTO.setOrderWork(original);

        // 原路退查询目标渠道和退款账户信息
        if (Objects.equals(refundDTO.getRefundType(), OrderConsts.ORDER_REFUND_TYPE_ONLINE)) {
            List<OrderPay> orderPays = orderPayService.listOrderPayByOrderIdAndWorkIdsAndTradeType(original.getOrderId(), Lists.newArrayList(original.getOrderId()), PayConsts.PAY_TRADE_TYPE_INTIME);
            List<OrderPay> collect = orderPays.stream()
                    .filter(e -> Objects.equals(e.getPayChannelId(), PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY)
                            || Objects.equals(e.getPayChannelId(), PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY))
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotNullOrEmpty(collect)) {
                OrderPay orderPay = collect.get(0);
                refundDTO.setPayTargetChannelId(orderPay.getPayChannelId());
                refundDTO.setPayeeThirdAccount(orderPay.getPayerThirdAccount());
                refundDTO.setPayeeThirdAccountName(orderPay.getPayerThirdAccountName());
            }
        }

        //保存退款
        refundBService.commitRefund(refundDTO);
    }

}
